package demo.basic.employeedb.xml;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.systinet.wasp.webservice.LookupException;
import org.systinet.wasp.webservice.Registry;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import demo.basic.employeedb.core.DBException;
import demo.basic.employeedb.core.Employee;
import demo.basic.employeedb.core.EmployeeDB;


public class EmployeeDBXMLProcessor {
	List<Employee> employees = new ArrayList<Employee>();
	private static String serviceWSDLPath = "/demo/basic/EmployeeDB/wsdl";
	private EmployeeDB employeeDBService = null;

	public EmployeeDBXMLProcessor(){
        String serverURL = System.getProperty("systinet.demo.server.url", "http://localhost:6060");

        // lookup of EmployeeDBService
		try {
			employeeDBService = (EmployeeDB)Registry.lookup(serverURL + serviceWSDLPath,
					EmployeeDB.class);
			try {
				for(int i=0;i<employees.size();i++)
					employeeDBService.add(employees.get(i));
			} catch (DBException e1) {
				System.out.println("ERROR: Could not add the employee");
				e1.printStackTrace();
			}
		} catch (LookupException e) {
			System.out.println("ERROR: Could not find the service");
			System.out.println("System shutdown");
			System.exit(1);
		}
	}

	public void loadEmployeeFromXMLFile(String filePath) {
		File f = new File(filePath);
		if(f.exists()){
			parse(f);
		} else {
			System.out.println("File "+filePath+" could not be found");
		}
	}

	public void addEmployeesToDB() {
		try {
			for (int i = 0; i < employees.size(); i++)
				employeeDBService.add(employees.get(i));
		} catch (DBException e1) {
			System.out.println("ERROR: Could not add the employee");
			e1.printStackTrace();
		}
	}

	public void saveEmployeeToXMLFile(String filePath) {
//		employees = employeeDBService.getAll();

		File f = new File(filePath);
		if(f.exists()){
			f.delete();
		}
		try {
			f.createNewFile();
			f = new File(filePath);
			System.out.println("File: "+f.getAbsolutePath());
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}

		DocumentBuilderFactory factory;
		DocumentBuilder builder;
		Document document;

		try{
			factory = DocumentBuilderFactory.newInstance();
			factory.setValidating(false);
			builder = factory.newDocumentBuilder();
			document = builder.newDocument();

			// Create employee list node
			Element emp_list_node = document.createElement("tns:EmployeeList");
			emp_list_node.setAttribute("xmlns:tns", "http://systinet.com/demo");
			emp_list_node.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
			document.appendChild(emp_list_node);

			for(Employee emp: employees) {
				Element emp_node = document.createElement("tns:Employee");
				emp_node.setAttribute("id", Integer.toString(emp.getId()));
				emp_node.setAttribute("name", emp.getName());
				emp_list_node.appendChild(emp_node);
			}

			// Save to XML
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

			DOMSource source = new DOMSource(document);
			StreamResult result = new StreamResult(f.toURI().getPath());
			transformer.transform(source, result);
		}
	    catch (ParserConfigurationException ex) {
	    	ex.printStackTrace();
	    }
	    catch (FactoryConfigurationError ex) {
	    	ex.printStackTrace();
	    }
	    catch (TransformerConfigurationException ex) {
	    	ex.printStackTrace();
	    }
	    catch (TransformerException ex) {
	    	ex.printStackTrace();
	    }
	}

	protected void parse(File file){
		DocumentBuilderFactory factory;
		DocumentBuilder builder;
		Document document;

		try{
			factory = DocumentBuilderFactory.newInstance();
			factory.setValidating(false);
			builder = factory.newDocumentBuilder();
			document = builder.parse(file);

			// tns:EmployeeList node
			Element rootNode = document.getDocumentElement();

			Node current_node;
			NodeList node_list = rootNode.getChildNodes();

			int l = node_list.getLength();

			for(int i=0;i<l;i++){
				current_node = node_list.item(i);
				if(current_node.getNodeType() == Node.TEXT_NODE)
					continue;

				String current_node_name = current_node.getNodeName();
				if(current_node_name.equals("tns:Employee")){
					parseEmployeeTag(current_node);
				}
			}
		}
	    catch (ParserConfigurationException ex) {
	    	ex.printStackTrace();
	    }
	    catch (FactoryConfigurationError ex) {
	    	ex.printStackTrace();
	    }
	    catch (IOException ex) {
	    	ex.printStackTrace();
	    }
	    catch (SAXException ex) {
	    	ex.printStackTrace();
	    }
	}

	private void parseEmployeeTag(Node emp_node) {
		String empName = emp_node.getAttributes().getNamedItem("name").getNodeValue();
		int empID = Integer.parseInt(emp_node.getAttributes().getNamedItem("id").getNodeValue());
		Employee emp = new Employee(empID, empName);
		employees.add(emp);
	}

    public static void main(String[] args) {
    	String inputXmlFile = args[0];
    	String outputXmlFile = args[1];
//    	String inputXmlFile = "schema/employee_list.xml";
//    	String outputXmlFile = "schema/existing_employee.xml";
    	EmployeeDBXMLProcessor processor = new EmployeeDBXMLProcessor();
    	processor.loadEmployeeFromXMLFile(inputXmlFile);
//    	processor.addEmployeesToDB();
    	processor.saveEmployeeToXMLFile(outputXmlFile);
    }
}
